Skip to content

feat: add solution pages with a11y and SEO compliance#134

Open
sinduri-g wants to merge 8 commits into
mainfrom
refactor/solution-detail-cleanup
Open

feat: add solution pages with a11y and SEO compliance#134
sinduri-g wants to merge 8 commits into
mainfrom
refactor/solution-detail-cleanup

Conversation

@sinduri-g

@sinduri-g sinduri-g commented Jun 10, 2026

Copy link
Copy Markdown
Contributor
  • New route /adventures/:id/levels/:levelId/solution with static prerendering
  • SolutionDetail.tsx: narrative hero, collapsible step cards, sidebar TOC, Codespaces card, outro ending
  • Solution data pipeline: types.ts, generate-solutions.mjs, barrel index.ts; prebuild now runs both generators
  • Beginner solution for Echoes Lost in Orbit with step-by-step YAML walkthrough and solution images (WebP)
  • ChallengeDetail: "Solution walkthrough" link surfaced at the bottom of each level
  • A11y: tabindex=-1 on details elements for fragment-nav focus movement; motion-reduce:transition-none on summary chevron; aria-live region for copy confirmation; blockquote replaced with div[role=note]
  • SEO: buildSitemapBody emits solution URLs when authored solution files exist; llms.txt includes solution page links; BreadcrumbList JSON-LD on solution pages
  • Project commands migrated from .claude/skills/ to .claude/commands/; add-solution command added

Type of change

  • feat new feature
  • fix bug fix
  • refactor no behavior change
  • docs / chore / config / perf / style / security

Manual checks

  • Screen reader tested (UI changes only)
  • New routes added to sitemap.xml, prerender array, README (routes only)

- New route `/adventures/:id/levels/:levelId/solution` with static prerendering
- SolutionDetail.tsx: narrative hero, collapsible step cards, sidebar TOC, Codespaces card, outro ending
- Solution data pipeline: types.ts, generate-solutions.mjs, barrel index.ts; `prebuild` now runs both generators
- Beginner solution for Echoes Lost in Orbit with step-by-step YAML walkthrough and solution images (WebP)
- ChallengeDetail: "Solution walkthrough" link surfaced at the bottom of each level
- A11y: tabindex=-1 on details elements for fragment-nav focus movement; motion-reduce:transition-none on summary chevron; aria-live region for copy confirmation; blockquote replaced with div[role=note]
- SEO: buildSitemapBody emits solution URLs when authored solution files exist; llms.txt includes solution page links; BreadcrumbList JSON-LD on solution pages
- Project commands migrated from .claude/skills/ to .claude/commands/; add-solution command added

Signed-off-by: Sinduri Guntupalli <sinduri.guntupalli@dynatrace.com>
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://off-on-dev.github.io/website/pr-preview/pr-134/

Built to branch gh-pages at 2026-06-12 14:06 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Adds an optional contributor field to the Solution type, rendered as a ContributorBadge (labelled "Solution Contributor") in the hero alongside the difficulty badge. Wired up for the Broken Echoes beginner solution with Katharina Sick.

Signed-off-by: Sinduri Guntupalli <sinduri.guntupalli@dynatrace.com>
…tests

- Check SOLUTIONS registry in ChallengeDetail loader so the walkthrough
  link only appears when a solution file has been authored, not just
  when the deadline has passed
- Add .catch() to clipboard writeText in SolutionDetail to surface
  failures instead of silently swallowing them
- Tighten prerender assertion from "Solution" to "Solution:" so the
  check only passes when a real authored solution title is rendered,
  not a fallback "Not Found" or locked state
- Update generate-solutions.mjs template to emit the same stricter
  assertion for future solutions

Signed-off-by: Sinduri Guntupalli <sinduri.guntupalli@dynatrace.com>
- Replace floating language label + absolute copy button with a header bar
  (label right-aligned, copy button in the pre area via md-copy-btn) so
  they never overlap at any viewport width
- Add overflow-wrap: break-word to md-content and md-inline inline code
  to prevent long file paths overflowing on mobile
- Show "What Was Fixed" step nav above the context section on mobile
  (lg:hidden in main column, hidden lg:block in sidebar)
- Fix prerender tests to read the solution HTML once in beforeAll
- Move contributor badge below intro text in SolutionHero
- Aggregate further reading links de-duped into a sidebar card
- Remove collapsible wrapper from context section (always-open)
- Update add-solution.md, ADVENTURES.md, and styleguide.md to reflect
  new contributor, outro, and further reading conventions

Signed-off-by: Sinduri Guntupalli <sinduri.guntupalli@dynatrace.com>
- Move `furtherReading` from `SolutionStep` to top-level `Solution` type;
  remove per-step aggregation/dedup in favour of a single authored list
- Add `loader` to `SolutionDetail`; `meta()` now uses loader data via
  `MetaFunction<typeof loader>`, eliminating duplicate `SOLUTIONS.find` calls
- Replace `<h2>` inside `<summary>` elements with `<span>` to fix unreliable
  AT heading navigation through `<details>/<summary>`
- Fix `BlockRenderer` and `TakeawaysList` index keys (`${type}-${i}` and
  `key={item}` respectively)
- Fix `patchRegion` silent failure: missing region markers now abort with
  an error instead of no-op
- Add `--validate-only` flag to `generate-solutions.mjs` and
  `generate:solutions:validate` npm script
- Fix `beforeAll` missing from vitest import in `prerender.test.ts`; replace
  hardcoded contributor/outro assertions with `SOLUTIONS` data lookups
- Add `src/test/solutionDetail.test.tsx`: page-state tests and `CodeBlock`
  copy-button tests (clipboard call, Copied state, 1500ms revert)

Signed-off-by: Sinduri Guntupalli <sinduri.guntupalli@dynatrace.com>
- Replace em dashes in aria-labels with colon/comma separators (AT reads — as "dash")
- Extract isSolutionUnlocked() to utils.ts; use in both ChallengeDetail and SolutionDetail loaders
- Rename loader field available → solutionUnlocked for clarity
- Add role="list" to solution steps <ol> (Tailwind preflight strips VoiceOver list semantics)
- Promote step titles from <span> to <h3> so heading-key navigation reaches them
- Replace <p> with <h2> for the solution walkthrough promo in ChallengeDetail
- Remove StepFooter passthrough; move null-guard into TakeawaysList
- Guard SolutionHero backstory div so empty role="note" is never rendered
- Fix topic pill and copy button touch targets to meet WCAG 2.5.8 (24px minimum)
- Use ReturnType<typeof loader> for useLoaderData generic in ChallengeDetail
- Fix ArrowRight icon size from 13 to 14
- Update all test fixtures to use solutionUnlocked and include deadline field

Signed-off-by: Sinduri Guntupalli <sinduri.guntupalli@dynatrace.com>
…t-in-orbit

- Add intermediate solution (The Silent Canary): three bugs in the
  AnalysisTemplate fixed step by step — wrong Prometheus service name,
  inverted success condition, and missing ready-containers query
- Add expert solution (Hyperspace Operations & Transport): OpenTelemetry
  Collector configuration walkthrough and three-metric canary analysis
- Add 12 WebP images for both levels
- Fix beginner solution: split kubectl commands with intermediate
  explanation, add missing apply command after auto-sync fix, restore
  self-healing outcome sentence, correct two-apps alt text
- Update add-solution command: remove two-takeaway cap, preserve all
  source takeaways; add note to not drop explanatory prose
- Generator patches: sitemap, llms.txt, smoke tests, prerender tests,
  SEO tests, react-router config, solutions index

Signed-off-by: Sinduri Guntupalli <sinduri.guntupalli@dynatrace.com>
- Guard navigator.clipboard with optional chaining to avoid synchronous TypeError in non-secure contexts
- Add explicit LoaderData return type to loader function
- Fix canonical URL trailing slash to match sitemap (/solution/)
- Lowercase overline label source text (CSS text-transform: uppercase handles display)

Signed-off-by: Sinduri Guntupalli <sinduri.guntupalli@dynatrace.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant